package handler

import (
	"context"
	"encoding/json"
	"github.com/afocus/captcha"
	"github.com/astaxie/beego/logs"
	"github.com/julienschmidt/httprouter"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/service/grpc"
	"github.com/micro/go-plugins/registry/consul"
	"ihome/models"
	addHouse "ihome/proto/addHouse"
	getArea "ihome/proto/getArea"
	getHouseInfo "ihome/proto/getHouseInfo"
	getHouses "ihome/proto/getHouses"
	getImageCd "ihome/proto/getImageCd"
	getIndex "ihome/proto/getIndex"
	getSession "ihome/proto/getSession"
	getSmsCd "ihome/proto/getSmsCd"
	getUserHouses "ihome/proto/getUserHouses"
	getUserInfo "ihome/proto/getUserInfo"
	login "ihome/proto/login"
	logout "ihome/proto/logout"
	register "ihome/proto/register"
	uploadAvatar "ihome/proto/uploadAvatar"
	uploadHouseImage "ihome/proto/uploadHouseImage"
	userAuth "ihome/proto/userAuth"
	"ihome/utils"
	"image"
	"image/png"
	"io/ioutil"
	"net/http"
	"regexp"
)

var service micro.Service

func GetArea(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {

	client := getArea.NewGetAreaService("go.micro.srv.getArea", service.Client())
	rsp, err := client.GetAreas(context.TODO(), &getArea.Request{})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	var areas []models.Area

	for _, value := range rsp.Data {
		tmp := models.Area{Id: int(value.Aid), Name: value.Aname}
		areas = append(areas, tmp)
	}

	utils.HandleJsonResponse(w, rsp.Code, areas)
}

// 获取首页轮播图
func GetIndex(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	logs.Info("获取首页轮播 GetIndex /api/v1.0/houses/index")

	client := getIndex.NewGetIndexService("go.micro.srv.getIndex", service.Client())

	rsp, err := client.SrvGetIndex(context.TODO(), &getIndex.Request{})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	var data []interface{}
	json.Unmarshal(rsp.Mix, &data)

	utils.HandleJsonResponse(w, utils.RecodeOk, data)
}

// 获取session信息
func GetSession(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	logs.Info("获取session信息 GetSession /api/v1.0/session")

	client := getSession.NewGetSessionService("go.micro.srv.getSession", service.Client())

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	rsp, err := client.SrvGetSession(context.TODO(), &getSession.Request{
		SessionId: cookie.Value,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	data := make(map[string]string)
	data["name"] = rsp.UserName

	utils.HandleJsonResponse(w, rsp.Code, data)
}

// 获取图片验证码
func GetImageCd(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	client := getImageCd.NewGetImageCdService("go.micro.srv.getImageCd", service.Client())

	uuid := ps.ByName("uuid")

	rsp, err := client.SrvGetImageCd(context.TODO(), &getImageCd.Request{Uuid: uuid})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	var img image.RGBA
	img.Stride = int(rsp.Stride)
	img.Pix = rsp.Pix
	img.Rect.Min.X = int(rsp.Min.X)
	img.Rect.Min.Y = int(rsp.Min.Y)
	img.Rect.Max.X = int(rsp.Max.X)
	img.Rect.Max.Y = int(rsp.Max.Y)

	var image captcha.Image

	image.RGBA = &img

	png.Encode(w, image)
}

// 获取短信验证码
func GetSmsCd(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("获取短信验证码 GetSmsCd /api/v1.0/smscode/:mobile")

	text := r.URL.Query()["text"][0]
	id := r.URL.Query()["id"][0]
	mobile := ps.ByName("mobile")

	mobile_reg := regexp.MustCompile(`0?(13|14|15|17|18|19)[0-9]{9}`)
	bo := mobile_reg.MatchString(mobile)
	if bo == false {
		utils.HandleJsonResponse(w, utils.RecodeMobileErr, nil)
		return
	}

	client := getSmsCd.NewGetSmsCdService("go.micro.srv.getSmsCd", service.Client())

	rsp, err := client.SrvGetSmsCd(context.TODO(), &getSmsCd.Request{
		Mobile:   mobile,
		Imagestr: text,
		Uuid:     id,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	utils.HandleJsonResponse(w, rsp.Code, nil)
}

// 注册
func Register(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("注册 Register /api/v1.0/users")

	var request map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	client := register.NewRegisterService("go.micro.srv.register", service.Client())

	mobile := request["mobile"].(string)
	password := request["password"].(string)
	smsCode := request["sms_code"].(string)

	if mobile == "" || password == "" || smsCode == "" {
		utils.HandleJsonResponse(w, utils.RecodeDataerr, nil)
		return
	}

	rsp, err := client.SrvRegister(context.TODO(), &register.Request{
		Mobile:   mobile,
		Password: password,
		SmsCode:  smsCode,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	// cookie操作
	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		cookie := http.Cookie{
			Name:   "userlogin",
			Value:  rsp.SessionId,
			Path:   "/",
			MaxAge: 3600,
		}
		http.SetCookie(w, &cookie)
	}

	utils.HandleJsonResponse(w, rsp.Code, nil)
}

// 登陆
func Login(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("登陆 Login /api/v1.0/sessions")

	var request map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	client := login.NewLoginService("go.micro.srv.login", service.Client())

	mobile := request["mobile"].(string)
	password := request["password"].(string)

	if mobile == "" || password == "" {
		utils.HandleJsonResponse(w, utils.RecodeDataerr, nil)
		return
	}

	rsp, err := client.SrvLogin(context.TODO(), &login.Request{
		Mobile:   mobile,
		Password: password,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	// cookie操作
	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		cookie := http.Cookie{
			Name:   "userlogin",
			Value:  rsp.SessionId,
			Path:   "/",
			MaxAge: 3600,
		}
		http.SetCookie(w, &cookie)
	}

	utils.HandleJsonResponse(w, rsp.Code, nil)
}

// 退出登录
func Logout(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("退出登录 Logout /api/v1.0/session")

	client := logout.NewLogoutService("go.micro.srv.logout", service.Client())

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	rsp, err := client.SrvLogout(context.TODO(), &logout.Request{
		SessionId: cookie.Value,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	// cookie操作
	newCookie := http.Cookie{
		Name:   "userlogin",
		Value:  "",
		Path:   "/",
		MaxAge: -1,
	}
	http.SetCookie(w, &newCookie)

	utils.HandleJsonResponse(w, rsp.Code, nil)
}

// 获取用户信息
func GetUserInfo(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("获取用户信息 GetUserInfo /api/v1.0/user")

	client := getUserInfo.NewGetUserInfoService("go.micro.srv.getUserInfo", service.Client())

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	rsp, err := client.SrvGetUserInfo(context.TODO(), &getUserInfo.Request{
		SessionId: cookie.Value,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	data := map[string]interface{}{
		"user_id": rsp.UserId,
		"name":  rsp.Name,
		"mobile": rsp.Mobile,
		"real_name": rsp.RealName,
		"id_card": rsp.IdCard,
		"avatar_url": utils.AddDomain2Url(rsp.AvatarUrl),
	}

	utils.HandleJsonResponse(w, rsp.Code, data)
}

// 上传用户头像
func UploadAvatar(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("上传用户头像 UploadAvatar /api/v1.0/user/avatar")

	file, fileHeader, err := r.FormFile("avatar")
	if err != nil {
		utils.HandleJsonResponse(w, utils.RecodeDataerr, nil)
		return
	}

	logs.Info("文件大小", fileHeader.Size)
	logs.Info("文件名", fileHeader.Filename)

	fileBuf := make([]byte, fileHeader.Size)
	_, err = file.Read(fileBuf)
	if err != nil {
		utils.HandleJsonResponse(w, utils.RecodeDataerr, nil)
		return
	}

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	client := uploadAvatar.NewUploadAvatarService("go.micro.srv.uploadAvatar", service.Client())
	rsp, err := client.SrvUploadAvatar(context.TODO(), &uploadAvatar.Request{
		SessionId: cookie.Value,
		FileExt: fileHeader.Filename,
		FileSize: fileHeader.Size,
		Avatar: fileBuf,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	data := map[string]interface{}{
		"avatar_url": utils.AddDomain2Url(rsp.AvatarUrl),
	}

	utils.HandleJsonResponse(w, rsp.Code, data)
}

// 用户信息检查
func GetUserAuth(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("用户信息检查 GetUserAuth /api/v1.0/user/auth")

	client := getUserInfo.NewGetUserInfoService("go.micro.srv.getUserInfo", service.Client())

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	rsp, err := client.SrvGetUserInfo(context.TODO(), &getUserInfo.Request{
		SessionId: cookie.Value,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	data := map[string]interface{}{
		"user_id": rsp.UserId,
		"name":  rsp.Name,
		"mobile": rsp.Mobile,
		"real_name": rsp.RealName,
		"id_card": rsp.IdCard,
		"avatar_url": utils.AddDomain2Url(rsp.AvatarUrl),
	}

	utils.HandleJsonResponse(w, rsp.Code, data)
}

// 实名认证
func UserAuth(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("实名认证 UserAuth /api/v1.0/user/auth")

	var request map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	realName := request["real_name"].(string)
	idCard := request["id_card"].(string)

	if realName == "" || idCard == "" {
		utils.HandleJsonResponse(w, utils.RecodeDataerr, nil)
		return
	}

	client := userAuth.NewUserAuthService("go.micro.srv.userAuth", service.Client())

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	rsp, err := client.SrvUserAuth(context.TODO(), &userAuth.Request{
		SessionId: cookie.Value,
		RealName: realName,
		IdCard: idCard,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	utils.HandleJsonResponse(w, rsp.Code, nil)
}


// 获取用户已发布房源
func GetUserHouses(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("获取用户已发布房源 GetUserHouses /api/v1.0/user/houses")

	client := getUserHouses.NewGetUserHousesService("go.micro.srv.getUserHouses", service.Client())

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	rsp, err := client.SrvGetUserHouses(context.TODO(), &getUserHouses.Request{
		SessionId: cookie.Value,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	var house_list []models.House
	json.Unmarshal(rsp.Mix, &house_list)

	var houses []interface{}

	for _, value := range house_list {
		houses = append(houses, value.To_house_info())
	}


	data := map[string]interface{}{
		"houses": houses,
	}

	utils.HandleJsonResponse(w, rsp.Code, data)
}

// 添加房源
func AddHouses(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("添加房源 AddHouses /api/v1.0/houses")

	// body就是json的二进制流
	body, _ := ioutil.ReadAll(r.Body)

	client := addHouse.NewAddHouseService("go.micro.srv.addHouse", service.Client())

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	rsp, err := client.SrvAddHouse(context.TODO(), &addHouse.Request{
		SessionId: cookie.Value,
		Body: body,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	data := map[string]interface{}{
		"house_id": rsp.HouseId,
	}

	utils.HandleJsonResponse(w, rsp.Code, data)
}

// 上传房屋图片
func UploadHouseImage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("上传房屋图片 UploadHouseImage /api/v1.0/houses/:id/images")

	houseId := ps.ByName("id")

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	file, fileHeader, err := r.FormFile("house_image")
	if err != nil {
		logs.Info("获取房屋图片文件错误", err)
		utils.HandleJsonResponse(w, utils.RecodeDataerr, nil)
		return
	}

	logs.Info("文件大小", fileHeader.Size)
	logs.Info("文件名", fileHeader.Filename)

	fileBuf := make([]byte, fileHeader.Size)
	_, err = file.Read(fileBuf)
	if err != nil {
		utils.HandleJsonResponse(w, utils.RecodeDataerr, nil)
		return
	}

	client := uploadHouseImage.NewUploadHouseImageService("go.micro.srv.uploadHouseImage", service.Client())
	rsp, err := client.SrvUploadHouseImage(context.TODO(), &uploadHouseImage.Request{
		SessionId: cookie.Value,
		Id: houseId,
		Image: fileBuf,
		FileSize: fileHeader.Size,
		FileName: fileHeader.Filename,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	data := map[string]interface{}{
		"url": utils.AddDomain2Url(rsp.Url),
	}

	utils.HandleJsonResponse(w, rsp.Code, data)
}

// 获取房屋信息
func GetHouseInfo(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	logs.Info("获取房屋信息 GetHouseInfo /api/v1.0/houses/:id")

	cookie, err := r.Cookie("userlogin")
	if err != nil || cookie.Value == "" {
		utils.HandleJsonResponse(w, utils.RecodeSessionerr, nil)
		return
	}

	id := ps.ByName("id")

	client := getHouseInfo.NewGetHouseInfoService("go.micro.srv.getHouseInfo", service.Client())

	rsp, err := client.SrvGetHouseInfo(context.TODO(), &getHouseInfo.Request{
		SessionId: cookie.Value,
		Id: id,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	house := models.House{}
	json.Unmarshal(rsp.HouseData, &house)

	data := map[string]interface{}{
		"user_id": int(rsp.UserId),
		"house": house.To_one_house_desc(),
	}

	utils.HandleJsonResponse(w, rsp.Code, data)
}

// 搜索房屋
func GetHouses(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	logs.Info("搜索房屋 GetHouses /api/v1.0/houses")

	client := getHouses.NewGetHousesService("go.micro.srv.getHouses", service.Client())

	aid := r.URL.Query()["aid"][0]
	sd := r.URL.Query()["sd"][0]
	ed := r.URL.Query()["ed"][0]
	sk := r.URL.Query()["sk"][0]
	p := r.URL.Query()["p"][0]

	rsp, err := client.SrvGetHouses(context.TODO(), &getHouses.Request{
		Aid: aid,
		Sd: sd,
		Ed: ed,
		Sk: sk,
		P: p,
	})
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	var houseList []interface{}
	json.Unmarshal(rsp.Houses, &houseList)

	data := map[string]interface{} {
		"current_page": rsp.CurrentPage,
		"houses": houseList,
		"total_page": rsp.TotalPage,
	}

	utils.HandleJsonResponse(w, utils.RecodeOk, data)
}

func init() {
	reg := consul.NewRegistry(func(op *registry.Options) {
		op.Addrs = []string{
			"127.0.0.1:8500",
		}
	})

	service = grpc.NewService()
	service.Init(micro.Registry(reg))
}
